package cn.codecang.mall.common.aop;

import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * WebLogAspect
 *
 * @author xiaoluo
 * @date 2023/6/3 21:41
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {
//    // 所有controller中的方法全部记录日志
//    @Pointcut("execution(public * cn.codecang.mall.controller..*.*(..))")
//    public void webLog() {
//    }
//
//    /**
//     * 在切点之前织入
//     *
//     * @param joinPoint 连接点
//     * @throws Throwable throwable
//     */
//    @Before("webLog()")
//    public void doBefore(@NotNull JoinPoint joinPoint) throws Throwable {
//        // 开始打印请求日志
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        assert attributes != null;
//        HttpServletRequest request = attributes.getRequest();
//        // 打印请求相关参数
//        log.info("========================================== 请求开始 ==========================================");
//        // 打印请求 url
//        log.info("URL            : {}", request.getRequestURL().toString());
//        // 打印 Http method
//        log.info("HTTP Method    : {}", request.getMethod());
//        // 打印调用 controller 的全路径以及执行方法
//        log.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
//        // 打印请求的 IP
//        log.info("IP             : {}", request.getRemoteAddr());
//        // 打印请求入参
//        log.info("请求参数        : {}", new Gson().toJson(joinPoint.getArgs()));
//    }
//
//    /**
//     * 在切点之后织入
//     *
//     * @throws Throwable throwable
//     */
//    @After("webLog()")
//    public void doAfter() throws Throwable {
//        log.info("=========================================== 请求结束 ===========================================");
//        // 每个请求之间空一行
//        log.info("");
//    }
//
//    /**
//     * 环绕
//     *
//     * @param proceedingJoinPoint 进行连接点
//     * @return {@link Object}
//     * @throws Throwable throwable
//     */
//    @Around("webLog()")
//    public Object doAround(@NotNull ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//        long startTime = System.currentTimeMillis();
//        Object result = proceedingJoinPoint.proceed();
//        // 打印出参
//        log.info("返回参数        : {}", new Gson().toJson(result));
//        // 执行耗时
//        log.info("消耗时间        : {} ms", System.currentTimeMillis() - startTime);
//        return result;
//    }

    // 在需要的方法上添加@LogAnnotation注解, 只在该方法上生效
    @Around("@annotation(cn.codecang.mall.common.aop.LogAnnotation)")
    public Object method(@NotNull ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object result = proceedingJoinPoint.proceed();
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        // 打印请求相关参数
        log.info("========================================== 请求开始 ==========================================");
        // 打印请求 url
        log.info("URL            : {}", request.getRequestURL().toString());
        // 打印 Http method
        log.info("HTTP Method    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("Class Method   : {}.{}", proceedingJoinPoint.getSignature().getDeclaringTypeName(), proceedingJoinPoint.getSignature().getName());
        // 打印请求的 IP
        log.info("IP             : {}", request.getRemoteAddr());
        // 打印请求入参
        log.info("请求参数        : {}", new Gson().toJson(proceedingJoinPoint.getArgs()));
        // 打印出参
        log.info("返回参数        : {}", new Gson().toJson(result));
        // 执行耗时
        log.info("消耗时间        : {} ms", System.currentTimeMillis() - startTime);

        log.info("=========================================== 请求结束 ===========================================");
        return result;
    }
}
